package com.hb.formation.planning.dao;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.Transactional;

public abstract class DaoGeneric<T> {

	// T = G�n�rique donc il faut donn� le Type de la classe qui va �tre utilis�
	private Class<T> entityType;
	private static Session session = null;
	private SessionFactory se;
	private ApplicationContext context= null;

	public DaoGeneric(Class<T> type) {
		this.setEntityType(type);
		
		if(session==null){
			if(context==null)
			{
				context = new ClassPathXmlApplicationContext("applicationContext.xml");
			}
			se = (SessionFactory) context.getBean("sessionFactory");
			if (session != null) {
				session = se.getCurrentSession();
			} else {
				session = se.openSession();
			}
		}
	}

	@Transactional(readOnly = true)
	public List<T> findAll() {
		// Find all pour n'importe quel type d'entit�... entityType=Entit�
		// rechercher (classe cible)
		return (List<T>) session.createQuery(
				"From " + getEntityType().getSimpleName()).list();
	}

	@Transactional(readOnly = true)
	public List<T> findAllBy(HashMap<String, List> liste) {
		/* on commence a construire la requete en recuperant le nom de la Classe */
		String query = "From " + getEntityType().getSimpleName() + " where ";
		/* On récupère les clés de la HashMap et on fait un iterator dessus */
		Set<String> cles = liste.keySet();
		Iterator it = cles.iterator();
		/*
		 * Pour chaque clé dans le tableau cles, on parcours le tableau associé
		 * à la clé dans la HashMap
		 */
		for (int i = 0; i < cles.size(); i++) {
			Object cle = it.next();
			List valeur = liste.get(cle);

			/* Si on a plus d'une valeur dans le tableau associé à la clé */
			if (valeur.size() > 1) {
				for (int j = 0; j < valeur.size() - 1; j++) { // pour toute les
																// valeurs sauf
																// la derniere
																// dans le
																// tableau
																// "valeur"
					query += "(" + cle + "='" + valeur.get(j) + "' OR ";
				}
				if (i != cles.size() - 1) {// Si on est pas sur l'avant dernier
											// index du tableau "cles"
					query += cle
							+ "='"
							+ valeur.get(valeur.size() - 1).toString()
									.replace("'", "''") + "') and";
				} else {
					query += cle
							+ "='"
							+ valeur.get(valeur.size() - 1).toString()
									.replace("'", "''") + "') ";
				}
			} else {// Si on a qu'une seule entrée dans le tableau "valeur"
				query += cle + "='" + valeur.get(valeur.size() - 1) + "'";
			}
		}

		List<T> result = getSession().createQuery(query).list();
		return result;
	}

	@Transactional
	public void insert(T object) {
		session.save(object);
	}

	@Transactional
	public void update(T object) {
		session.saveOrUpdate(object);
	}

	@Transactional
	public void delete(T object) {
		session.delete(object);
	}

	public Session getSession() {
		return session;
	}

	public void setSession(Session session) {
		this.session = session;
	}

	public Class<T> getEntityType() {
		return entityType;
	}

	public void setEntityType(Class<T> entityType) {
		this.entityType = entityType;
	}
}
